// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// #import {isAndroid, isIOS} from './cr.m.js';

cr.define('cr.icon', function() {
  /**
   * @return {!Array<number>} The scale factors supported by this platform for
   *     webui resources.
   */
  function getSupportedScaleFactors() {
    const supportedScaleFactors = [];
    if (!cr.isIOS) {
      // This matches the code in ResourceBundle::InitSharedInstance() that
      // supports SCALE_FACTOR_100P on all non-iOS platforms.
      supportedScaleFactors.push(1);
    }
    if (!cr.isIOS && !cr.isAndroid) {
      // All desktop platforms support zooming which also updates the renderer's
      // device scale factors (a.k.a devicePixelRatio), and these platforms have
      // high DPI assets for 2x.  Let the renderer pick the closest image for
      // the current device scale factor.
      supportedScaleFactors.push(2);
    } else {
      // For other platforms that use fixed device scale factor, use
      // the window's device pixel ratio.
      // TODO(oshima): Investigate corresponding to
      // ResourceBundle::InitSharedInstance() more closely.
      supportedScaleFactors.push(window.devicePixelRatio);
    }
    return supportedScaleFactors;
  }

  /**
   * Generates a CSS url string.
   * @param {string} s The URL to generate the CSS url for.
   * @return {string} The CSS url string.
   */
  /* #export */ function getUrlForCss(s) {
    // http://www.w3.org/TR/css3-values/#uris
    // Parentheses, commas, whitespace characters, single quotes (') and double
    // quotes (") appearing in a URI must be escaped with a backslash
    const s2 = s.replace(/(\(|\)|\,|\s|\'|\"|\\)/g, '\\$1');
    return `url("${s2}")`;
  }

  /**
   * A URL for the filetype icon for |filePath|. OS and theme dependent.
   * @param {string} filePath
   * @return {string}
   */
  /* #export */ function getFileIconUrl(filePath) {
    const url = new URL('chrome://fileicon/');
    url.searchParams.set('path', filePath);
    url.searchParams.set('scale', window.devicePixelRatio + 'x');
    return url.toString();
  }

  /**
   * Generates a CSS -webkit-image-set for a chrome:// url.
   * An entry in the image set is added for each of getSupportedScaleFactors().
   * The scale-factor-specific url is generated by replacing the first instance
   * of 'scalefactor' in |path| with the numeric scale factor.
   *
   * @param {string} path The URL to generate an image set for.
   *     'scalefactor' should be a substring of |path|.
   * @return {string} The CSS -webkit-image-set.
   */
  function getImageSet(path) {
    const supportedScaleFactors = getSupportedScaleFactors();

    const replaceStartIndex = path.indexOf('SCALEFACTOR');
    if (replaceStartIndex < 0) {
      return getUrlForCss(path);
    }

    let s = '';
    for (let i = 0; i < supportedScaleFactors.length; ++i) {
      const scaleFactor = supportedScaleFactors[i];
      const pathWithScaleFactor = path.substr(0, replaceStartIndex) +
          scaleFactor + path.substr(replaceStartIndex + 'scalefactor'.length);

      s += getUrlForCss(pathWithScaleFactor) + ' ' + scaleFactor + 'x';

      if (i !== supportedScaleFactors.length - 1) {
        s += ', ';
      }
    }
    return '-webkit-image-set(' + s + ')';
  }

  /**
   * Returns the URL of the image, or an image set of URLs for the provided
   * path.  Resources in chrome://theme have multiple supported scale factors.
   *
   * @param {string} path The path of the image.
   * @return {string} The url, or an image set of URLs.
   */
  /* #export */ function getImage(path) {
    const chromeThemePath = 'chrome://theme';
    const isChromeThemeUrl =
        (path.slice(0, chromeThemePath.length) === chromeThemePath);
    return isChromeThemeUrl ? getImageSet(path + '@SCALEFACTORx') :
                              getUrlForCss(path);
  }

  function getBaseFaviconUrl() {
    const faviconUrl = new URL('chrome://favicon2/');
    faviconUrl.searchParams.set('size', '16');
    faviconUrl.searchParams.set('scale_factor', 'SCALEFACTORx');
    return faviconUrl;
  }

  /**
   * Creates a CSS -webkit-image-set for a favicon.
   *
   * @param {string} url URL of the favicon
   * @return {string} -webkit-image-set for the favicon
   */
  /* #export */ function getFavicon(url) {
    const faviconUrl = getBaseFaviconUrl();
    faviconUrl.searchParams.set('icon_url', url);
    return getImageSet(faviconUrl.toString());
  }

  /**
   * Creates a CSS -webkit-image-set for a favicon request based on a page URL.
   *
   * @param {string} url URL of the original page
   * @param {boolean} isSyncedUrlForHistoryUi Should be set to true only if the
   *     caller is an UI aimed at displaying user history, and the requested url
   *     is known to be present in Chrome sync data.
   * @param {string} remoteIconUrlForUma In case the entry is contained in sync
   *     data, we can pass the associated icon url.
   * @param {number} size The favicon size.
   *
   * @return {string} -webkit-image-set for the favicon.
   */
  /* #export */ function getFaviconForPageURL(
      url, isSyncedUrlForHistoryUi, remoteIconUrlForUma = '', size = 16) {
    // Note: URL param keys used below must match those in the description of
    // chrome://favicon2 format in components/favicon_base/favicon_url_parser.h.
    const faviconUrl = getBaseFaviconUrl();
    faviconUrl.searchParams.set('size', size);
    faviconUrl.searchParams.set('page_url', url);
    // TODO(dbeam): use the presence of 'allow_google_server_fallback' to
    // indicate true, otherwise false.
    const fallback = isSyncedUrlForHistoryUi ? '1' : '0';
    faviconUrl.searchParams.set('allow_google_server_fallback', fallback);
    if (isSyncedUrlForHistoryUi) {
      faviconUrl.searchParams.set('icon_url', remoteIconUrlForUma);
    }

    return getImageSet(faviconUrl.toString());
  }

  // #cr_define_end
  console.warn('crbug/1173575, non-JS module files deprecated.');
  return {
    getFavicon: getFavicon,
    getFaviconForPageURL: getFaviconForPageURL,
    getFileIconUrl: getFileIconUrl,
    getImage: getImage,
    getUrlForCss: getUrlForCss,
  };
});
